﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Collections;
using System.IO;
using common;
using i_core;
using Autofac;
using i_core.usr;
using System.Threading;
using System.Threading.Tasks;
using i_core.net;
using i_core.p_enum;
using client35.json;
using db_util;
using System.Net;
using System.Text.RegularExpressions;
using client35.Properties;

namespace client35 {
	public partial class MinChat : Form {
		public static GlobalData.PhoneType _PhoneType;

		private bool CopyFlag = false;
		private IntPtr nextClipboardViewer = (IntPtr)0;
		private static int CallTimeLength = 0;

		public static GlobalData.DropDialData _DropDialData = new GlobalData.DropDialData();

		public base_user_info u_info;

		public static i_connect connect;

		private readonly i_log log;

		private readonly CancellationTokenSource cancel_source;

		private int wait_user_pickup = 0;

		public MinChat(i_user_info user_info) {
			Control.CheckForIllegalCrossThreadCalls = false;
			InitializeComponent();

			if (cancel_source is null)
				cancel_source = new CancellationTokenSource();

			log = global_vars.scope.ResolveKeyed<i_log>(log_type.log4net,
					new NamedParameter("user", "system"),
					new NamedParameter("islog", true)
			);

			u_info = user_info as base_user_info;

			Win32API.SetClipboardViewer(Handle.ToInt32());
			IntiForm();
		}

		private async void IntiForm() {
			try {
				this.AgentInfo_TT.SetToolTip(this, u_info.user_name + " :" + u_info.role_name + " \r\n:" + u_info.group_name);

				this.NoAnswer_flag.Visible = false;
				this.CallIn_Flag.Visible = false;
				//this.CallRecord_Tsmi.Text += "  (15)";

				//register sip server
				{
					if (!await sip_reg.run(u_info.acc, cancel_source.Token)) {
						this.tsmi_sipserver.Image = Properties.Resources.red;
						throw new Exception($"sip({u_info.acc}) register failed");
					}
					this.tsmi_sipserver.Image = Properties.Resources.green;
					sip_reg.sip_stack.sip_new_comming =
						(caller_num, callee_num) => {
							wait_user_pickup = 0;
							var phone_info = get_full_number(caller_num);
							this.panel1.Visible = true;
							Width = 180;
							this.Opacity = 1;
							this.lbl_phone_info.Text = $"{phone_info.Key}({phone_info.Value})";
							this.lbl_call_state.Text = "来电响铃中";
							CallTimeLength = 0;
							CallTimeLength_Timer.Start();
							u_info.call_state = e_call_state.ringback;

							var ring_cancel_souce = new CancellationTokenSource();
							Task.Run(
								() => {
									while (ring_cancel_souce != null && !ring_cancel_souce.IsCancellationRequested) {
										sip_param.m_pPlayer.Play("Audio\\ringing.wav", 1);
										Thread.Sleep(3000);
									}
								});

							while (true) {
								if (wait_user_pickup != 0)
									break;
								Thread.Sleep(200);
							}
							ring_cancel_souce.Cancel();
							ring_cancel_souce.Dispose();
							return wait_user_pickup == 1;
						};
					log.Info($"sip({u_info.acc}) register successful");
				}

				//connect socket server
				{
					var local_ip = Settings.Default.current_ip;
					log.Debug($"local ip:{local_ip}");
					connect = global_vars.scope.ResolveKeyed<i_connect>(
						e_connect_type.socket,
						new NamedParameter("svr_ip", u_info.u_param.conn_svr_ip),
						new NamedParameter("svr_port", u_info.u_param.conn_svr_port),
						new NamedParameter("local_ip", local_ip),
						new NamedParameter("local_port", u_info.u_param.conn_local_port));

					if (!connect.is_connected) {
						this.tsmi_callserver.Image = Properties.Resources.red;
						throw new Exception($"socket({u_info.u_param.conn_svr_ip}:{u_info.u_param.conn_svr_port}) connectted failed");
					}
					this.tsmi_callserver.Image = Properties.Resources.green;
					this.tsi_server.Image = Properties.Resources.green;
					_ = connect_run(cancel_source.Token);

					log.Info("connect socket server successful");
				}
			} catch (Exception ex) {
				log.Error("initilizate form error", ex);
			}
		}


		private async Task<bool> connect_run(CancellationToken cancel_token) {
			var task_source = new TaskCompletionSource<bool>();
			var cancel_source = new CancellationTokenSource();
			cancel_token.Register(() => {
				if (!cancel_source.IsCancellationRequested) {
					cancel_source.Cancel();
					cancel_source.Dispose();
				}
			});

			try {
				if (connect is null)
					throw new Exception("socket hasn't connectted");

				//subscribe login response
				connect.login_event.Subscribe(
					m => {
						log.Debug("receive a login response");
						if (m.code == 1) {
							if (u_info.u_param.auto_open_page == 1)
								System.Diagnostics.Process.Start("explorer.exe", u_info.u_param.home_url);

							this.BackgroundImage = Properties.Resources.logo;

							log.Debug("login server successful");
						}
					});

				//subscribe answer response
				connect.answer_event.Subscribe(
					m => {
						log.Debug("receive a answer response");
						if (m.code == 1) {
							u_info.call_state = e_call_state.answer;
							this.lbl_call_state.Text = "已接通";
							CallTimeLength = 0;
						}
					});

				//subscribe terminate response
				connect.terminate_event.Subscribe(
					m => {
						log.Debug("receive a terminate response");
						if (m.code == 1) {
							u_info.call_state = e_call_state.idle;
							this.lbl_call_state.Text = "已挂机";
							this.CallTimeLength_Timer.Stop();
							this.CallIn_Flag.Visible = false;
							this.lbl_phone_info.Text = "";
							this.lbl_call_state.Text = "";
							this.Width = 40;
							this.panel1.Visible = false;
							sip_param.m_pPlayer.Play("Audio\\hangup.wav", 1);
						}
					});
				//subscribe exit response
				connect.exit_event.Subscribe(
					m => {
						log.Debug("receive a login response");
						if (m.code == 1) {
							if (u_info.u_param.auto_open_page == 1)
								System.Diagnostics.Process.Start("explorer.exe", u_info.u_param.home_url);

							this.BackgroundImage = Properties.Resources.logo;

							log.Debug("login server successful");
						}
					});

				//subscribe recording response
				connect.recording_event.Subscribe(
					m => {
						log.Debug("receive a recording response");
						if (m.code == 1) {
							if (u_info.call_state == e_call_state.dialing) {
								u_info.call_state = e_call_state.ring;
								this.lbl_call_state.Text = "正在响铃";
								CallTimeLength = 0;
							}
						}
					});

				//subscribe skt_ka_event response
				connect.skt_ka_event.Subscribe(
					m => {
						log.Debug("receive a login response");
						if (m.code == 1) {
							if (u_info.u_param.auto_open_page == 1)
								System.Diagnostics.Process.Start("explorer.exe", u_info.u_param.home_url);

							this.BackgroundImage = Properties.Resources.logo;

							log.Debug("login server successful");
						}
					});

				//subscribe skt_call_event response
				connect.skt_call_event.Subscribe(
					m => {
						log.Debug("receive a call response");
						if (m.code == 1) {

							log.Debug("login server successful");
						}
					});

				//send login request to server
				await connect.send_message_info(connect.p_login_info(u_info));

			} catch (Exception ex) {
				log.Error("process response error", ex);
			}

			return await task_source.Task;
		}

		protected override void DefWndProc(ref Message m) {
			#region 系统回调函数
			switch (m.Msg) {
				case (int)Win32API.WinMsg.WM_DRAWCLIPBOARD: //复制事件
					{
						if (CopyFlag && Clipboard.ContainsText()) {
							string temp = Clipboard.GetText();
							string numbertemp = "";
							if (!string.IsNullOrEmpty(temp.Trim()) && temp.Length <= 15 && temp.Length >= 6) {
								foreach (char ch in temp.ToCharArray()) {
									if (ch >= 48 && ch <= 57 || ch.Equals('#') || ch.Equals('*')) {
										numbertemp += ch.ToString();
									}
								}
								if (!string.IsNullOrEmpty(numbertemp)) {

									if (numbertemp.Length >= 6 && numbertemp.Length <= 13) {
										_DropDialData.DialNum = numbertemp;
										_DropDialData.ContentName = "未知";
										_DropDialData.PhoneAddress = "未知";
										this.Width = 180;
										this.panel1.Visible = true;
										this.lbl_phone_info.Text = numbertemp;
										this.lbl_call_state.Text = "双击拨打";
									}
								}
							}

						}
						this.CopyFlag = true;
						Win32API.SendMessage(nextClipboardViewer, m.Msg, m.WParam, m.LParam);
					}
					break;
				case (int)Win32API.WinMsg.WM_HOTKEY: {
						string w = m.WParam.ToString();
						string l = m.LParam.ToString();
						string r = m.Result.ToString();
					}
					break;
				default:
					base.DefWndProc(ref m);
					break;
			}
			#endregion
		}

		private void MinChat_MouseDoubleClick(object sender, MouseEventArgs e) {
			///来电时，双击可摘机
			///空闲时，双击可拨号
			///通话时，双击可挂断
			switch (u_info.call_state) {
				case e_call_state.idle:
					if (!string.IsNullOrEmpty(this.lbl_phone_info.Text)) {
						DialNumber(this.lbl_phone_info.Text);
					}
					break;
				case e_call_state.ringback:
					u_info.call_state = e_call_state.answer;
					this.CallIn_Flag.Visible = true;
					//this.lbl_phone_info.Text = _DropDialData.DialNum + "(" + _DropDialData.PhoneAddress + ")";
					this.lbl_call_state.Text = "已接通";
					this.Width = 180;
					CallTimeLength = 0;
					this.panel1.Visible = true;
					wait_user_pickup = 1;
					break;
				case e_call_state.answer:
				case e_call_state.ring:
				case e_call_state.dialing:
					u_info.call_state = e_call_state.idle;

					this.CallIn_Flag.Visible = false;
					this.lbl_phone_info.Text = "";
					this.lbl_call_state.Text = "";
					this.Width = 40;
					this.panel1.Visible = false;
					this.CallTimeLength_Timer.Stop();
					var bye_info = connect.p_terminate_info(u_info, "");
					_ = connect.send_message_info(bye_info);
					sip_param.m_pPlayer.Play("Audio\\hangup.wav", 1);
					break;
			}
		}

		private bool DialNumber(string Number) {
			bool DialResult = false;
			var phone_info = get_full_number(Number);
			this.panel1.Visible = true;
			Width = 180;
			this.Opacity = 1;
			this.lbl_phone_info.Text = $"{phone_info.Key}({phone_info.Value})";
			this.lbl_call_state.Text = "正在拨号中";

			u_info.call_state = e_call_state.dialing;
			var dial_info = connect.p_dial_info(u_info, "", phone_info.Key);
			_ = connect.send_message_info(dial_info);
			CallTimeLength = 0;
			this.CallTimeLength_Timer.Start();
			return DialResult;
		}

		private KeyValuePair<string, string> get_full_number(string number) {
			var s_number = u_info.u_param.auto_add_num_local_flag == 1 ? u_info.u_param.auto_add_num_local + number : number;
			var s_city = "未知";
			try {
				if (!number.StartsWith("0") && number.Length > 7) {
					var num = number.Substring(0, 7);
					var phone_model = call_phoneaddress_util.GetModel(num);
					if (phone_model != null) {
						if (u_info.u_param.local_city_code == phone_model.area_code) {
							s_number = u_info.u_param.auto_add_num_local_flag == 1 ? u_info.u_param.auto_add_num_local + number : number;
							s_city = u_info.u_param.local_city;
						} else {
							s_number = u_info.u_param.auto_add_num_remote_flag == 1 ? u_info.u_param.auto_add_num_remote + number : number;
							s_city = $"{phone_model.province} {phone_model.area}";
						}
					}
				}
			} catch {

			}

			return new KeyValuePair<string, string>(s_number, s_city);
		}

		private void MinChat_FormClosing(object sender, FormClosingEventArgs e) {
			try {

				_ = sip_reg.end();
				if (connect != null && connect.is_connected) {
					var exit_info = connect.p_exit_info(u_info, "");
					_ = connect.send_message_info(exit_info);
				}
			} catch (Exception ex) {
				MessageBox.Show(ex.Message);
			}
		}

		private void MinChat_KeyPress(object sender, KeyPressEventArgs e) {
			var input_str = Regex.Replace(e.KeyChar.ToString(), @"[^\d.\d]", "");
			if (!input_str.IsEmpty()) {
				this.panel1.Visible = true;
				this.Width = 180;
				this.lbl_phone_info.Tag += e.KeyChar.ToString();
				this.lbl_phone_info.Text = this.lbl_phone_info.Tag + "";
			}
		}

		private void lbl_phone_info_TextChanged(object sender, EventArgs e) {

		}
	}
}
